home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / misc / volume2 / mcat < prev    next >
Encoding:
Internet Message Format  |  1991-08-07  |  8.0 KB

  1. From: rich@oxtrap.UUCP (K. Richard Magill)
  2. Newsgroups: comp.sources.misc
  3. Subject: v02i043: mcat - a cat utility for mmap only devices
  4. Message-ID: <7179@ncoast.UUCP>
  5. Date: 3 Feb 88 02:32:06 GMT
  6. Approved: allbery@ncoast.UUCP
  7.  
  8. Comp.sources.misc: Volume 2, Issue 43
  9. Submitted-By: "K. Richard Magill" <rich@oxtrap.UUCP>
  10. Archive-Name: mcat
  11.  
  12. [For Sequents in particular and 4.xBSD with mmap() in general.  ++bsa]
  13.  
  14. Note: This program uses getopt(3) which doesn't ordinarily exist in
  15. the berkeley universe.  The at&t code for getopt is around and has
  16. been released into the public domain.  (At least, that's my
  17. understanding).
  18.  
  19. #!/bin/sh
  20. # This is a shell archive, meaning:                              
  21. # 1. Remove everything above the #! /bin/sh line.                
  22. # 2. Save the resulting test in a file.                          
  23. # 3. Execute the file with /bin/sh (not csh) to create the files:
  24. #    mcat.l
  25. #    mcat.c
  26. # This archive created:  Fri Nov 27 18:19:07 EST 1987 by rich@oxtrap
  27. echo extracting mcat.l
  28. sed 's/^X//' >mcat.l << 'END-of-mcat.l'
  29. X.TH MCAT l "27 Nov 87" "local"
  30. X.SH NAME
  31. Xmcat \- cat like program for read/write'ing pmap devices from shell
  32. X.SH SYNOPSIS
  33. X.B mcat
  34. X[-b buffersize] [-i ifile] [-o ofile] [-s] [-v]
  35. X.SH DESCRIPTION
  36. X.I mcat
  37. Xis a program very much like cat or dd that is capable of reading a
  38. Xnon-read(2)'able device, for example, an mmap(2) only device like
  39. Xsequent's pmap devices.  It is capable of copying mmap to mmap,
  40. Xreading and writing onto mmap or reading from mmap and writing.
  41. X.SH OPTIONS
  42. X.PP
  43. X.TP 14
  44. X.B \-b buffersize
  45. Xuse buffersize as the buffer size for read's and write's rather than BUFSIZ.
  46. X.PP
  47. X.TP 14
  48. X.B \-i ifile
  49. Xuse ifile as file name for input rather than stdin.
  50. X.PP
  51. X.TP 14
  52. X.B \-o ofile
  53. Xuse ofile as file name for output rather than stdout.
  54. X.PP
  55. X.TP 14
  56. X.B \-s
  57. Xprint no error messages.  (silent).
  58. X.PP
  59. X.TP 14
  60. X.B \-v
  61. Xprint some log lines.  (verbose).
  62. X.SH BUGS
  63. XDue to a synergy of shell strategy, and balance hardware limitations,
  64. Xyou can not redirect stdout to a pmap device on sequent balance.  (but
  65. Xyou can use -o ofile).
  66. X.SH AUTHOR
  67. XK. Richard Magill - Digital Works Ltd.
  68. X
  69. Xrich@oxtrap.UUCP, rich@sendai.UUCP
  70. END-of-mcat.l
  71. echo extracting mcat.c
  72. sed 's/^X//' >mcat.c << 'END-of-mcat.c'
  73. X/*
  74. X * This file is mcat.c and contains a sort of cat utility for use with
  75. X * pmap devices.  It was originally written on sequent Dynix 2.1.1.
  76. X *
  77. X * to do:
  78. X *    mmap disk files.
  79. X *    mcat multiple files in, out.
  80. X *    -x write at offset x.
  81. X *    trunc old disk files.
  82. X *
  83. X * Original Author: K. Richard Magill Fri Nov 20 16:00:53 EST 1987
  84. X * Last Mod Fri Nov 27 18:06:15 EST 1987, by rich@oxtrap
  85. X *
  86. X *$Header: /u1/rich/bin/src/RCS/mcat.c,v 1.1 87/11/27 18:06:45 rich Exp $
  87. X */
  88. X
  89. X#include <stdio.h>
  90. X#include <sys/types.h>
  91. X#include <sys/file.h>
  92. X#include <sys/ioctl.h>
  93. X#include <sys/mman.h>
  94. X#include <sys/stat.h>
  95. X#include <machine/pmap.h>
  96. X
  97. X#define Perror(s)    {if(Silent==0)perror(s);}
  98. X
  99. Xchar *valloc();
  100. X
  101. Xmain(argc, argv)
  102. Xint argc;
  103. Xchar *argv[];
  104. X{
  105. X    char *InBase = ((char *) 0);
  106. X    char *OutBase = ((char *) 0);
  107. X
  108. X    int BufferSize = BUFSIZ;
  109. X    int InPut = fileno(stdin);
  110. X    int OutPut = fileno(stdout);
  111. X    int Silent = 0;
  112. X    int Verbose = 0;
  113. X    int WriteFlags = 0;
  114. X    int c;
  115. X
  116. X    struct pmap_ioc InSize, OutSize;
  117. X    struct stat Readable;
  118. X
  119. X    extern char *optarg;
  120. X    extern int optind;
  121. X
  122. X/*
  123. X * parse args.
  124. X */
  125. X
  126. X    while ((c = getopt(argc, argv, "b:i:o:sv")) != EOF) {
  127. X        switch (c) {
  128. X
  129. X        case 'b':
  130. X            BufferSize = atoi(optind);
  131. X
  132. X            if (Verbose != 0) {
  133. X                (void) fprintf(stderr,
  134. X                           "%s: Using %d byte i/o.\n",
  135. X                           argv[0], BufferSize);
  136. X            } /* verbose */
  137. X
  138. X            break;
  139. X
  140. X        case 'i':
  141. X
  142. X            if ((InPut = open(optarg, O_RDONLY, 0666)) < 0) {
  143. X                Perror("opening input:");
  144. X                exit(1);
  145. X            } /* on error opening for read */
  146. X
  147. X            break;
  148. X
  149. X        case 'o':
  150. X            if (access(optarg, F_OK) == 0) {
  151. X                if (Verbose != 0) {
  152. X                    (void) fprintf(stderr, "%s: output exists.\n", argv[0]);
  153. X                } /* verbose */
  154. X
  155. X                if (access(optarg, R_OK) == 0) {
  156. X                    if (Verbose != 0) {
  157. X                        (void) fprintf(stderr, "%s: output is readable.\n", argv[0]);
  158. X                    } /* verbose */
  159. X
  160. X                    WriteFlags |= O_RDWR;
  161. X                }
  162. X
  163. X            } else {
  164. X                if (Verbose != 0) {
  165. X                    (void) fprintf(stderr, "%s: output does not exist.  creating.\n", argv[0]);
  166. X                } /* verbose */
  167. X
  168. X                WriteFlags = O_CREAT | O_RDWR;
  169. X            }
  170. X
  171. X            if ((OutPut = open(optarg, WriteFlags, 0666)) < 0) {
  172. X                Perror("mcat: opening output");
  173. X                exit(1);
  174. X            } /* on error opening for write */
  175. X
  176. X            break;
  177. X
  178. X        case 's':
  179. X            Silent = 1;
  180. X            break;
  181. X
  182. X        case 'v':
  183. X            Verbose = 1;
  184. X            break;
  185. X
  186. X        case '?':
  187. X        default:
  188. X            if (Silent == 0) {
  189. X                (void) fprintf(stderr, "%s: usage: -b buffer_size -i input_file -o output_file -s -v\n", argv[0]);
  190. X            } /* not silent */
  191. X
  192. X            exit(1);
  193. X
  194. X        } /* switch on switch character */
  195. X    } /* while there are switch characters */
  196. X
  197. X/*
  198. X * I presume that if the ioctl fails, this is not a pmap device and we
  199. X * aren't mapping.  If you know of a better way to check a a descriptor
  200. X * for mmap'ability, (short of chasing the major number through the kernel),
  201. X * let me know.
  202. X */
  203. X
  204. X    if (ioctl(InPut, PMAPIOCGETP, &InSize) == 0) { /* not pmap */
  205. X        if ((InBase = valloc(InSize.pi_size)) == 0) {
  206. X            Perror("valloc'ing output buffer:");
  207. X            exit(1);
  208. X        } /* on error valloc'ing */
  209. X
  210. X        if (mmap(InBase, InSize.pi_size, PROT_READ, MAP_SHARED,
  211. X             InPut, 0) != 0) {
  212. X            Perror("on error mmap'ing input:");
  213. X            exit(1);
  214. X        } /* on error mmap'ing input */
  215. X
  216. X        if (Verbose != 0) {
  217. X            (void) fprintf(stderr, "%s: mmap'ing input.\n",
  218. X                       argv[0]);
  219. X        } /* verbose */
  220. X
  221. X    } /* not mapped or not mappable */
  222. X
  223. X    if ((ioctl(OutPut, PMAPIOCGETP, &OutSize) == 0)) { /* not mapping */
  224. X        if  ((OutBase = valloc(OutSize.pi_size)) == 0) {
  225. X            Perror("valloc'ing for output buffer:");
  226. X            exit(1);
  227. X        } /* on valloc error */
  228. X
  229. X        if (mmap(OutBase, OutSize.pi_size, PROT_RDWR, MAP_SHARED,
  230. X             OutPut, 0) != 0) {
  231. X            Perror("mmap'ing output:");
  232. X
  233. X            if (Silent == 0) {
  234. X                (void) fprintf(stderr, "%s: remember you can't redirect output.\n", argv[0]);
  235. X            } /* not silent */
  236. X
  237. X            exit(1);
  238. X        } /* on error mmap'ing output */
  239. X
  240. X        if (Verbose != 0) {
  241. X            (void) fprintf(stderr, "%s: mmap'ing output.\n",
  242. X                       argv[0]);
  243. X        } /* verbose */
  244. X
  245. X    } /* not mapped or not mappable */
  246. X
  247. X    if (InBase != ((char *) NULL)) { /* mapping input */
  248. X        if (OutBase != ((char *) NULL)) { /* and output */
  249. X            bcopy(InBase, OutBase,
  250. X                  (InSize.pi_size < OutSize.pi_size)
  251. X                  ? InSize.pi_size : OutSize.pi_size);
  252. X
  253. X        } else { /* map in, no map out */
  254. X            int ReallyWrote;
  255. X
  256. X            while (InSize.pi_size > 0) {
  257. X                if (BufferSize > InSize.pi_size) {
  258. X                    BufferSize = InSize.pi_size;
  259. X                } /* if buffer now holds it all */
  260. X
  261. X                if ((ReallyWrote = write(OutPut, InBase,
  262. X                             BufferSize)) == -1) {
  263. X                    Perror("writing output:");
  264. X                    exit(1);
  265. X                } /* on error writing */
  266. X
  267. X                InSize.pi_size -= ReallyWrote;
  268. X                InBase += ReallyWrote;
  269. X            }    /* while data to write */
  270. X        } /* if mapping output */
  271. X
  272. X    } else { /* not mapping input */
  273. X
  274. X        if (OutBase != ((char *) NULL)) { /* but mapping output */                int ReallyRead = 1;
  275. X
  276. X            while (ReallyRead != 0 && OutSize.pi_size > 0) {
  277. X                if (BufferSize > OutSize.pi_size) {
  278. X                    BufferSize = OutSize.pi_size;
  279. X                } /* if buffer now holds it all */
  280. X
  281. X                if ((ReallyRead = read(InPut, OutBase,
  282. X                             BufferSize)) == -1) {
  283. X                    Perror("reading input:");
  284. X                    exit(1);
  285. X                } /* on error reading */
  286. X
  287. X                OutSize.pi_size -= ReallyRead;
  288. X                OutBase += ReallyRead;
  289. X            }    /* while data to write */
  290. X
  291. X        } else { /* mapping nothing, should use cat instead */
  292. X            if (Silent == 0) {
  293. X                (void) fprintf(stderr, "%s: not mapping anything.  use cat instead.\n", argv[0]);
  294. X            } /* not silent */
  295. X
  296. X            exit(1);
  297. X        } /* if mapping output */
  298. X    } /* if mapping input */
  299. X
  300. X    exit(0);
  301. X} /* main() */
  302. X
  303. X/*
  304. X * $Log:    mcat.c,v $
  305. X * Revision 1.1  87/11/27  18:06:45  rich
  306. X * Initial revision
  307. X * 
  308. X *
  309. X * Local Variables:
  310. X * comment-column: 0
  311. X * fill-column: 75
  312. X * fill-prefix: " * "
  313. X * mode: c
  314. X * version-control: t
  315. X * End:
  316. X */
  317. X
  318. X/* end of mcat.c */
  319. END-of-mcat.c
  320. exit
  321.